home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / ghostview / SelFile.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  21KB  |  749 lines

  1. /*
  2.  * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and its
  5.  * documentation for any purpose and without fee is hereby granted, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Software Research Associates not be used
  9.  * in advertising or publicity pertaining to distribution of the software
  10.  * without specific, written prior permission.  Software Research Associates
  11.  * makes no representations about the suitability of this software for any
  12.  * purpose.  It is provided "as is" without express or implied warranty.
  13.  *
  14.  * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  15.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  16.  * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  18.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  19.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  * Author: Erik M. van der Poel
  23.  *         Software Research Associates, Inc., Tokyo, Japan
  24.  *         erik@sra.co.jp
  25.  */
  26.  
  27. /*
  28.  * Author's address:
  29.  *
  30.  *     erik@sra.co.jp
  31.  *                                            OR
  32.  *     erik%sra.co.jp@uunet.uu.net
  33.  *                                            OR
  34.  *     erik%sra.co.jp@mcvax.uucp
  35.  *                                            OR
  36.  *     try junet instead of co.jp
  37.  *                                            OR
  38.  *     Erik M. van der Poel
  39.  *     Software Research Associates, Inc.
  40.  *     1-1-1 Hirakawa-cho, Chiyoda-ku
  41.  *     Tokyo 102 Japan. TEL +81-3-234-2692
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <errno.h>
  46. /* BSD 4.3 errno.h does not declare errno */
  47. extern int errno;
  48. extern int sys_nerr;
  49. extern char *sys_errlist[];
  50.  
  51. #include <sys/param.h>
  52. #include <X11/cursorfont.h>
  53. #include <X11/Intrinsic.h>
  54. #include <X11/StringDefs.h>
  55. #include <X11/Composite.h>
  56. #include <X11/Shell.h>
  57. #include <X11/Xaw/Form.h>
  58. #include <X11/Xaw/Command.h>
  59. #include <X11/Xaw/Scrollbar.h>
  60. #include <X11/Xaw/Label.h>
  61.  
  62. #include "SFinternal.h"
  63.  
  64. #ifndef MAXPATHLEN
  65. #define MAXPATHLEN 1024
  66. #endif /* ndef MAXPATHLEN */
  67.  
  68. #if !defined(SVR4) && !defined(SYSV) && !defined(USG)
  69. extern char *getwd();
  70. #endif /* !defined(SVR4) && !defined(SYSV) && !defined(USG) */
  71.  
  72. int SFstatus = SEL_FILE_NULL;
  73.  
  74. char
  75.     SFstartDir[MAXPATHLEN],
  76.     SFcurrentPath[MAXPATHLEN],
  77.     SFcurrentDir[MAXPATHLEN];
  78.  
  79. Widget
  80.     selFile,
  81.     selFileCancel,
  82.     selFileField,
  83.     selFileForm,
  84.     selFileHScroll,
  85.     selFileHScrolls[3],
  86.     selFileLists[3],
  87.     selFileOK,
  88.     selFilePrompt,
  89.     selFileVScrolls[3];
  90.  
  91. Display *SFdisplay;
  92.  
  93. Pixel SFfore, SFback;
  94.  
  95. Atom    SFwmDeleteWindow;
  96.  
  97. XSegment SFsegs[2], SFcompletionSegs[2];
  98.  
  99. XawTextPosition SFtextPos;
  100.  
  101. int SFupperX, SFlowerY, SFupperY;
  102.  
  103. int SFtextX, SFtextYoffset;
  104.  
  105. int SFentryWidth, SFentryHeight;
  106.  
  107. int SFlineToTextH = 3;
  108.  
  109. int SFlineToTextV = 3;
  110.  
  111. int SFbesideText = 3;
  112.  
  113. int SFaboveAndBelowText = 2;
  114.  
  115. int SFcharsPerEntry = 15;
  116.  
  117. int SFlistSize = 10;
  118.  
  119. int SFworkProcAdded = 0;
  120.  
  121. XtAppContext SFapp;
  122.  
  123. int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
  124.  
  125. char SFtextBuffer[MAXPATHLEN];
  126.  
  127. XtIntervalId SFdirModTimerId;
  128.  
  129. int (*SFfunc)();
  130.  
  131. static char *oneLineTextEditTranslations = "\
  132.     <Key>Return:    redraw-display()\n\
  133.     Ctrl<Key>M:    redraw-display()\n\
  134. ";
  135.  
  136. /* ARGSUSED */
  137. static void
  138. SFexposeList(w, n, event)
  139.     Widget        w;
  140.     int        n;
  141.     XExposeEvent    *event;
  142. {
  143.     if ((event->type == NoExpose) || event->count) {
  144.         return;
  145.     }
  146.  
  147.     SFdrawList(n, SF_DO_NOT_SCROLL);
  148. }
  149.  
  150. /* ARGSUSED */
  151. static void
  152. SFmodVerifyCallback(w, client_data, event)
  153.     Widget            w;
  154.     XtPointer        client_data;
  155.     XKeyPressedEvent    *event;
  156. {
  157.     char    buf[2];
  158.  
  159.     if (
  160.         (XLookupString(event, buf, 2, NULL, NULL) == 1) &&
  161.         ((*buf) == '\r')
  162.     ) {
  163.         SFstatus = SEL_FILE_OK;
  164.     } else {
  165.         SFstatus = SEL_FILE_TEXT;
  166.     }
  167. }
  168.  
  169. /* ARGSUSED */
  170. static void
  171. SFokCallback(w)
  172.     Widget    w;
  173. {
  174.     SFstatus = SEL_FILE_OK;
  175. }
  176.  
  177. static XtCallbackRec SFokSelect[] = {
  178.     { SFokCallback, (XtPointer) NULL },
  179.     { NULL, (XtPointer) NULL },
  180. };
  181.  
  182. /* ARGSUSED */
  183. static void
  184. SFcancelCallback(w)
  185.     Widget    w;
  186. {
  187.     SFstatus = SEL_FILE_CANCEL;
  188. }
  189.  
  190. static XtCallbackRec SFcancelSelect[] = {
  191.     { SFcancelCallback, (XtPointer) NULL },
  192.     { NULL, (XtPointer) NULL },
  193. };
  194.  
  195. /* ARGSUSED */
  196. static void
  197. SFdismissAction(w, event, params, num_params)
  198.     Widget    w;
  199.     XEvent *event;
  200.     String *params;
  201.     Cardinal *num_params;
  202. {
  203.     if (event->type == ClientMessage &&
  204.         event->xclient.data.l[0] != SFwmDeleteWindow) return;
  205.  
  206.     SFstatus = SEL_FILE_CANCEL;
  207. }
  208.  
  209. static char *wmDeleteWindowTranslation = "\
  210.     <Message>WM_PROTOCOLS:    SelFileDismiss()\n\
  211. ";
  212.  
  213. static XtActionsRec actions[] = {
  214.     {"SelFileDismiss",    SFdismissAction},
  215. };
  216.  
  217. static void
  218. SFcreateWidgets(toplevel, prompt, ok, cancel)
  219.     Widget    toplevel;
  220.     char    *prompt;
  221.     char    *ok;
  222.     char    *cancel;
  223. {
  224.     int        i, n;
  225.     int        listWidth, listHeight;
  226.     int        listSpacing = 10;
  227.     int        scrollThickness = 15;
  228.     int        hScrollX, hScrollY;
  229.     int        vScrollX, vScrollY;
  230.     Cursor
  231.             xtermCursor,
  232.             sbRightArrowCursor,
  233.             dotCursor;
  234.     Arg        arglist[20];
  235.  
  236.     i = 0;
  237.     XtSetArg(arglist[i], XtNtransientFor, toplevel);        i++;
  238.  
  239.     selFile = XtAppCreateShell("selFile", "SelFile",
  240.         transientShellWidgetClass, SFdisplay, arglist, i);
  241.  
  242.     /* Add WM_DELETE_WINDOW protocol */
  243.     XtAppAddActions(XtWidgetToApplicationContext(selFile),
  244.         actions, XtNumber(actions));
  245.     XtOverrideTranslations(selFile,
  246.         XtParseTranslationTable(wmDeleteWindowTranslation));
  247.  
  248.     i = 0;
  249.     XtSetArg(arglist[i], XtNdefaultDistance, 30);            i++;
  250.     selFileForm = XtCreateManagedWidget("selFileForm",
  251.         formWidgetClass, selFile, arglist, i);
  252.  
  253.     i = 0;
  254.     XtSetArg(arglist[i], XtNlabel, prompt);                i++;
  255.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  256.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  257.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  258.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  259.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  260.     XtSetArg(arglist[i], XtNborderWidth, 0);            i++;
  261.     selFilePrompt = XtCreateManagedWidget("selFilePrompt",
  262.         labelWidgetClass, selFileForm, arglist, i);
  263.  
  264.     i = 0;
  265.     XtSetArg(arglist[i], XtNforeground, &SFfore);            i++;
  266.     XtSetArg(arglist[i], XtNbackground, &SFback);            i++;
  267.     XtGetValues(selFilePrompt, arglist, i);
  268.  
  269.     SFinitFont();
  270.  
  271.     SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
  272.             SFbesideText;
  273.     SFentryHeight = SFaboveAndBelowText + SFcharHeight +
  274.             SFaboveAndBelowText;
  275.  
  276.     listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
  277.             scrollThickness;
  278.     listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  279.             SFlineToTextV + SFlistSize * SFentryHeight +
  280.             SFlineToTextV + 1 + scrollThickness;
  281.  
  282.     SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
  283.  
  284.     hScrollX = -1;
  285.     hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  286.             SFlineToTextV + SFlistSize * SFentryHeight +
  287.             SFlineToTextV;
  288.     SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
  289.  
  290.     vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
  291.     vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
  292.     SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
  293.             SFlineToTextV;
  294.  
  295.     SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
  296.     SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  297.             SFlineToTextV;
  298.     SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
  299.             SFlineToTextV + SFlistSize * SFentryHeight - 1;
  300.  
  301.     SFtextX = SFlineToTextH + SFbesideText;
  302.     SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
  303.  
  304.     SFsegs[0].x1 = 0;
  305.     SFsegs[0].y1 = vScrollY;
  306.     SFsegs[0].x2 = vScrollX - 1;
  307.     SFsegs[0].y2 = vScrollY;
  308.     SFsegs[1].x1 = vScrollX;
  309.     SFsegs[1].y1 = 0;
  310.     SFsegs[1].x2 = vScrollX;
  311.     SFsegs[1].y2 = vScrollY - 1;
  312.  
  313.     SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
  314.     SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
  315.         SFlineToTextH + SFentryWidth - 1;
  316.  
  317.     i = 0;
  318.     XtSetArg(arglist[i], XtNwidth, 3 * listWidth + 2 * listSpacing + 4);
  319.                                     i++;
  320.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  321.  
  322.     XtSetArg(arglist[i], XtNfromVert, selFilePrompt);        i++;
  323.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  324.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  325.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  326.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  327.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  328.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  329.     XtSetArg(arglist[i], XtNstring, SFtextBuffer);            i++;
  330.     XtSetArg(arglist[i], XtNlength, MAXPATHLEN);            i++;
  331.     XtSetArg(arglist[i], XtNeditType, XawtextEdit);            i++;
  332.     XtSetArg(arglist[i], XtNwrap, XawtextWrapWord);            i++;
  333.     XtSetArg(arglist[i], XtNresize, XawtextResizeHeight);        i++;
  334.     XtSetArg(arglist[i], XtNuseStringInPlace, True);        i++;
  335.     selFileField = XtCreateManagedWidget("selFileField",
  336.         asciiTextWidgetClass, selFileForm, arglist, i);
  337.  
  338.     XtOverrideTranslations(selFileField,
  339.         XtParseTranslationTable(oneLineTextEditTranslations));
  340.     XtSetKeyboardFocus(selFileForm, selFileField);
  341.  
  342.     i = 0;
  343.     XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);    i++;
  344.     XtSetArg(arglist[i], XtNwidth, SFpathScrollWidth);        i++;
  345.     XtSetArg(arglist[i], XtNheight, scrollThickness);        i++;
  346.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  347.     XtSetArg(arglist[i], XtNfromVert, selFileField);        i++;
  348.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  349.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  350.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  351.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  352.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  353.     selFileHScroll = XtCreateManagedWidget("selFileHScroll",
  354.         scrollbarWidgetClass, selFileForm, arglist, i);
  355.  
  356.     XtAddCallback(selFileHScroll, XtNjumpProc,
  357.         SFpathSliderMovedCallback, (XtPointer) NULL);
  358.     XtAddCallback(selFileHScroll, XtNscrollProc,
  359.         SFpathAreaSelectedCallback, (XtPointer) NULL);
  360.  
  361.     i = 0;
  362.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  363.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  364.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  365.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  366.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  367.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  368.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  369.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  370.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  371.     selFileLists[0] = XtCreateManagedWidget("selFileList1",
  372.         compositeWidgetClass, selFileForm, arglist, i);
  373.  
  374.     i = 0;
  375.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  376.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  377.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  378.     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[0]);        i++;
  379.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  380.     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);        i++;
  381.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  382.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  383.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  384.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  385.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  386.     selFileLists[1] = XtCreateManagedWidget("selFileList2",
  387.         compositeWidgetClass, selFileForm, arglist, i);
  388.  
  389.     i = 0;
  390.     XtSetArg(arglist[i], XtNwidth, listWidth);            i++;
  391.     XtSetArg(arglist[i], XtNheight, listHeight);            i++;
  392.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  393.     XtSetArg(arglist[i], XtNfromHoriz, selFileLists[1]);        i++;
  394.     XtSetArg(arglist[i], XtNfromVert, selFileHScroll);        i++;
  395.     XtSetArg(arglist[i], XtNhorizDistance, listSpacing);        i++;
  396.     XtSetArg(arglist[i], XtNvertDistance, 10);            i++;
  397.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  398.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  399.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  400.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  401.     selFileLists[2] = XtCreateManagedWidget("selFileList3",
  402.         compositeWidgetClass, selFileForm, arglist, i);
  403.  
  404.     for (n = 0; n < 3; n++) {
  405.  
  406.         i = 0;
  407.         XtSetArg(arglist[i], XtNx, vScrollX);            i++;
  408.         XtSetArg(arglist[i], XtNy, vScrollY);            i++;
  409.         XtSetArg(arglist[i], XtNwidth, scrollThickness);    i++;
  410.         XtSetArg(arglist[i], XtNheight, SFvScrollHeight);    i++;
  411.         XtSetArg(arglist[i], XtNborderColor, SFfore);        i++;
  412.         selFileVScrolls[n] = XtCreateManagedWidget("selFileVScroll",
  413.             scrollbarWidgetClass, selFileLists[n], arglist, i);
  414.  
  415.         XtAddCallback(selFileVScrolls[n], XtNjumpProc,
  416.             SFvFloatSliderMovedCallback, (XtPointer) n);
  417.         XtAddCallback(selFileVScrolls[n], XtNscrollProc,
  418.             SFvAreaSelectedCallback, (XtPointer) n);
  419.  
  420.         i = 0;
  421.  
  422.         XtSetArg(arglist[i], XtNorientation, XtorientHorizontal);
  423.                                     i++;
  424.         XtSetArg(arglist[i], XtNx, hScrollX);            i++;
  425.         XtSetArg(arglist[i], XtNy, hScrollY);            i++;
  426.         XtSetArg(arglist[i], XtNwidth, SFhScrollWidth);        i++;
  427.         XtSetArg(arglist[i], XtNheight, scrollThickness);    i++;
  428.         XtSetArg(arglist[i], XtNborderColor, SFfore);        i++;
  429.         selFileHScrolls[n] = XtCreateManagedWidget("selFileHScroll",
  430.             scrollbarWidgetClass, selFileLists[n], arglist, i);
  431.  
  432.         XtAddCallback(selFileHScrolls[n], XtNjumpProc,
  433.             SFhSliderMovedCallback, (XtPointer) n);
  434.         XtAddCallback(selFileHScrolls[n], XtNscrollProc,
  435.             SFhAreaSelectedCallback, (XtPointer) n);
  436.     }
  437.  
  438.     i = 0;
  439.     XtSetArg(arglist[i], XtNlabel, ok);                i++;
  440.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  441.     XtSetArg(arglist[i], XtNcallback, SFokSelect);            i++;
  442.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  443.     XtSetArg(arglist[i], XtNfromVert, selFileLists[0]);        i++;
  444.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  445.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  446.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  447.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  448.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  449.     selFileOK = XtCreateManagedWidget("selFileOK", commandWidgetClass,
  450.         selFileForm, arglist, i);
  451.  
  452.     i = 0;
  453.     XtSetArg(arglist[i], XtNlabel, cancel);                i++;
  454.     XtSetArg(arglist[i], XtNresizable, True);            i++;
  455.     XtSetArg(arglist[i], XtNcallback, SFcancelSelect);        i++;
  456.     XtSetArg(arglist[i], XtNborderColor, SFfore);            i++;
  457.     XtSetArg(arglist[i], XtNfromHoriz, selFileOK);            i++;
  458.     XtSetArg(arglist[i], XtNfromVert, selFileLists[0]);        i++;
  459.     XtSetArg(arglist[i], XtNhorizDistance, 30);            i++;
  460.     XtSetArg(arglist[i], XtNvertDistance, 30);            i++;
  461.     XtSetArg(arglist[i], XtNtop, XtChainTop);            i++;
  462.     XtSetArg(arglist[i], XtNbottom, XtChainTop);            i++;
  463.     XtSetArg(arglist[i], XtNleft, XtChainLeft);            i++;
  464.     XtSetArg(arglist[i], XtNright, XtChainLeft);            i++;
  465.     selFileCancel = XtCreateManagedWidget("selFileCancel",
  466.         commandWidgetClass, selFileForm, arglist, i);
  467.  
  468.     XtSetMappedWhenManaged(selFile, False);
  469.     XtRealizeWidget(selFile);
  470.  
  471.     /* Add WM_DELETE_WINDOW protocol */
  472.     SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
  473.     XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
  474.  
  475.     SFcreateGC();
  476.  
  477.     xtermCursor = XCreateFontCursor(SFdisplay, XC_xterm);
  478.  
  479.     sbRightArrowCursor = XCreateFontCursor(SFdisplay, XC_sb_right_arrow);
  480.     dotCursor = XCreateFontCursor(SFdisplay, XC_dot);
  481.  
  482.     XDefineCursor(SFdisplay, XtWindow(selFileForm), xtermCursor);
  483.     XDefineCursor(SFdisplay, XtWindow(selFileField), xtermCursor);
  484.  
  485.     for (n = 0; n < 3; n++) {
  486.         XDefineCursor(SFdisplay, XtWindow(selFileLists[n]),
  487.             sbRightArrowCursor);
  488.     }
  489.     XDefineCursor(SFdisplay, XtWindow(selFileOK), dotCursor);
  490.     XDefineCursor(SFdisplay, XtWindow(selFileCancel), dotCursor);
  491.  
  492.     for (n = 0; n < 3; n++) {
  493.         XtAddEventHandler(selFileLists[n], ExposureMask, True,
  494.             SFexposeList, (XtPointer) n);
  495.         XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
  496.             SFenterList, (XtPointer) n);
  497.         XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
  498.             SFleaveList, (XtPointer) n);
  499.         XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
  500.             SFmotionList, (XtPointer) n);
  501.         XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
  502.             SFbuttonPressList, (XtPointer) n);
  503.         XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
  504.             SFbuttonReleaseList, (XtPointer) n);
  505.     }
  506.  
  507.     XtAddEventHandler(selFileField, KeyPressMask, False,
  508.         SFmodVerifyCallback, (XtPointer) NULL);
  509.  
  510.     SFapp = XtWidgetToApplicationContext(selFile);
  511.  
  512. }
  513.  
  514. /* position widget under the cursor */
  515. void
  516. SFpositionWidget(w)
  517.     Widget w;
  518. {
  519.     Arg args[3];
  520.     Cardinal num_args;
  521.     Dimension width, height, b_width;
  522.     int x, y, max_x, max_y;
  523.     Window root, child;
  524.     int dummyx, dummyy;
  525.     unsigned int dummymask;
  526.     
  527.     XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &x, &y,
  528.           &dummyx, &dummyy, &dummymask);
  529.     num_args = 0;
  530.     XtSetArg(args[num_args], XtNwidth, &width); num_args++;
  531.     XtSetArg(args[num_args], XtNheight, &height); num_args++;
  532.     XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
  533.     XtGetValues(w, args, num_args);
  534.  
  535.     width += 2 * b_width;
  536.     height += 2 * b_width;
  537.  
  538.     x -= ( (Position) width/2 );
  539.     if (x < 0) x = 0;
  540.     if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
  541.  
  542.     y -= ( (Position) height/2 );
  543.     if (y < 0) y = 0;
  544.     if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
  545.     
  546.     num_args = 0;
  547.     XtSetArg(args[num_args], XtNx, x); num_args++;
  548.     XtSetArg(args[num_args], XtNy, y); num_args++;
  549.     XtSetValues(w, args, num_args);
  550. }
  551.  
  552. FILE *
  553. SFopenFile(name, mode, prompt, failed)
  554.     char *name;
  555.     char *mode;
  556.     char *prompt;
  557.     char *failed;
  558. {
  559.     Arg args[1];
  560.     FILE *fp;
  561.  
  562.     SFchdir(SFstartDir);
  563.     if ((fp = fopen(name, mode)) == NULL) {
  564.     char *buf;
  565.     if (errno <= sys_nerr) {
  566.         buf = XtMalloc(strlen(failed) + strlen(sys_errlist[errno]) + 
  567.                strlen(prompt) + 2);
  568.         strcpy(buf, failed);
  569.         strcat(buf, sys_errlist[errno]);
  570.         strcat(buf, "\n");
  571.         strcat(buf, prompt);
  572.     } else {
  573.         buf = XtMalloc(strlen(failed) + strlen(prompt) + 2);
  574.         strcpy(buf, failed);
  575.         strcat(buf, "\n");
  576.         strcat(buf, prompt);
  577.     }
  578.     XtSetArg(args[0], XtNlabel, buf);
  579.     XtSetValues(selFilePrompt, args, 1);
  580.     XtFree(buf);
  581.     return NULL;
  582.     }
  583.     return fp;
  584. }
  585.  
  586. SFtextChanged()
  587. {
  588.  
  589.     if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) {
  590.         (void) strcpy(SFcurrentPath, SFtextBuffer);
  591.  
  592.         SFtextPos = XawTextGetInsertionPoint(selFileField);
  593.     } else {
  594.         (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
  595.  
  596.         SFtextPos = XawTextGetInsertionPoint(selFileField) +
  597.             strlen(SFstartDir);
  598.     }
  599.  
  600.     if (!SFworkProcAdded) {
  601.         (void) XtAppAddWorkProc(SFapp, SFworkProc, NULL);
  602.         SFworkProcAdded = 1;
  603.     }
  604.  
  605.     SFupdatePath();
  606. }
  607.  
  608. static char *
  609. SFgetText()
  610. {
  611.     return strcpy(XtMalloc((unsigned) (strlen(SFtextBuffer) + 1)),
  612.         SFtextBuffer);
  613. }
  614.  
  615. static
  616. SFprepareToReturn()
  617. {
  618.     SFstatus = SEL_FILE_NULL;
  619.     XtRemoveGrab(selFile);
  620.     XtUnmapWidget(selFile);
  621.     XtRemoveTimeOut(SFdirModTimerId);
  622.     if (SFchdir(SFstartDir)) {
  623.         XtAppError(
  624.             SFapp,
  625.             "XsraSelFile: can't return to current directory"
  626.         );
  627.     }
  628. }
  629.  
  630. FILE *
  631. XsraSelFile(toplevel, prompt, ok, cancel, failed,
  632.         init_path, mode, show_entry, name_return)
  633.     Widget        toplevel;
  634.     char        *prompt;
  635.     char        *ok;
  636.     char        *cancel;
  637.     char        *failed;
  638.     char        *init_path;
  639.     char        *mode;
  640.     int        (*show_entry)();
  641.     char        **name_return;
  642. {
  643.     static int    firstTime = 1;
  644.     int        i;
  645.     Arg        arglist[20];
  646.     XEvent        event;
  647.     FILE        *fp;
  648.  
  649.     if (!prompt) {
  650.         prompt = "Pathname:";
  651.     }
  652.  
  653.     if (!ok) {
  654.         ok = "OK";
  655.     }
  656.  
  657.     if (!cancel) {
  658.         cancel = "Cancel";
  659.     }
  660.  
  661.     if (firstTime) {
  662.         firstTime = 0;
  663.         SFdisplay = XtDisplay(toplevel);
  664.         SFcreateWidgets(toplevel, prompt, ok, cancel);
  665.     } else {
  666.         i = 0;
  667.  
  668.         XtSetArg(arglist[i], XtNlabel, prompt);            i++;
  669.         XtSetValues(selFilePrompt, arglist, i);
  670.  
  671.         i = 0;
  672.         XtSetArg(arglist[i], XtNlabel, ok);            i++;
  673.         XtSetValues(selFileOK, arglist, i);
  674.  
  675.         i = 0;
  676.         XtSetArg(arglist[i], XtNlabel, cancel);            i++;
  677.         XtSetValues(selFileCancel, arglist, i);
  678.     }
  679.  
  680.     SFpositionWidget(selFile);
  681.     XtMapWidget(selFile);
  682.  
  683. #if defined(SVR4) || defined(SYSV) || defined(USG)
  684.     if (!getcwd(SFstartDir, MAXPATHLEN)) {
  685. #else /* defined(SVR4) || defined(SYSV) || defined(USG) */
  686.     if (!getwd(SFstartDir)) {
  687. #endif /* defined(SVR4) || defined(SYSV) || defined(USG) */
  688.  
  689.         XtAppError(SFapp, "XsraSelFile: can't get current directory");
  690.     }
  691.     (void) strcat(SFstartDir, "/");
  692.     (void) strcpy(SFcurrentDir, SFstartDir);
  693.  
  694.     if (init_path) {
  695.         if (init_path[0] == '/') {
  696.             (void) strcpy(SFcurrentPath, init_path);
  697.             if (strncmp(
  698.                 SFcurrentPath,
  699.                 SFstartDir,
  700.                 strlen(SFstartDir)
  701.             )) {
  702.                 SFsetText(SFcurrentPath);
  703.             } else {
  704.                 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  705.             }
  706.         } else {
  707.             (void) strcat(strcpy(SFcurrentPath, SFstartDir),
  708.                 init_path);
  709.             SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
  710.         }
  711.     } else {
  712.         (void) strcpy(SFcurrentPath, SFstartDir);
  713.     }
  714.  
  715.     SFfunc = show_entry;
  716.  
  717.     SFtextChanged();
  718.  
  719.     XtAddGrab(selFile, True, True);
  720.  
  721.     SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
  722.         SFdirModTimer, (XtPointer) NULL);
  723.  
  724.     while (1) {
  725.         XtAppNextEvent(SFapp, &event);
  726.         XtDispatchEvent(&event);
  727.         switch (SFstatus) {
  728.         case SEL_FILE_TEXT:
  729.             SFstatus = SEL_FILE_NULL;
  730.             SFtextChanged();
  731.             break;
  732.         case SEL_FILE_OK:
  733.             *name_return = SFgetText();
  734.             if (fp = SFopenFile(*name_return, mode,
  735.                         prompt, failed)) {
  736.                 SFprepareToReturn();
  737.                 return fp;
  738.             }
  739.             SFstatus = SEL_FILE_NULL;
  740.             break;
  741.         case SEL_FILE_CANCEL:
  742.             SFprepareToReturn();
  743.             return NULL;
  744.         case SEL_FILE_NULL:
  745.             break;
  746.         }
  747.     }
  748. }
  749.